Okay, so we are almost finished with the lobby, and the last thing we need to do here is to further
improve the lobbies ambience.
We can do this by flickering the lights inside of our game and making our Squidward friend here disappear.
And then we can go ahead and replace him with our handsome Squidward monster that will go randomly somewhere
on this map.
So over here we have some of the models for our handsome Squidward.
So when the lights go out and the building becomes dark, we can place this guy somewhere on the map.
So that way when the person sitting there in the lobby, they will see this creepy dude staring at them,
so it'll add a nice ambience effect.
Now I have these invisible parts placed all over the workspace.
You'll see one right here in this position where Squidward is at.
I believe I have another one right here in the kitchen.
There are some up here, like there's one up here.
I believe I have one over here somewhere.
There's one.
And I believe there's another one back here.
Yep.
And all these different parts.
We're going to use the keyframe on them to position our handsome Squidward randomly on the map.
So as you can see, we have six different positions that we can go ahead and place them, and when the
lights go out, we're going to put them at one of these random positions just so it looks nice.
And our lobby has a bit of ambience to it.
So to get started, we can go ahead and go into the server and script the last module script we need
to complete, which is going to be our Squidward service.
And this is going to handle all of the animations for this.
Squidward and that Squidward, and flickering the lights and moving the squidwards around so we can
go ahead and open this bad boy up.
And the only two surfaces we're going to need in here is replicated storage.
And then we're also going to need the sound service.
Then we can create the table that will represent the service.
So squid.
Word service, and then we can go ahead and return that service at the very end here.
And we're only going to need one function to start the service.
We're not going to have to initialize anything in the service.
So we can just do function inside of our Squidward service and we'll call it start.
And we'll go ahead and fill this out later.
Now, some of the variables we're going to need in here is quite a few.
The first thing we need to make a reference to is that play sound event in replicated storage.
So replicated storage, dot events, dot remotes and get the play sound event.
That way we can tell the player to play sounds on their end.
And then we're also going to get all of the different flickering sounds that we have within our ambience
folder.
So there's a light flicker folder here, and there are two flicker sounds that we have that we're going
to play when we flicker the lights on and off.
So we can go ahead and call this flicker sounds.
Equal the sound service dot ambience dot light flicker and we'll get all the children.
And then we're also going to get all of the different random positions that we have for our handsome
Squidward.
So what we need to do is create a variable.
I'll call it random positions is equal to workspace, and it's inside of the characters folder.
So dot characters.
And then get positions, and then we'll go ahead and get all of those different positions.
And then I also have a default position inside of here.
If I go to it, and this is going to be where we're going to place our handsome Squidward when he's
not being moved around the map.
So he'll be outside of the player's view and he'll just be chilling here before we start moving him.
So that's going to be our default position.
So default position is equal to workspace dot characters dot default position.
Next up we need to make a reference to our regular Squidward who's at the counter.
So Reg, Squidward is equal to workspace dot characters and he's called Regular Squidward.
And then we're going to also get the humanoid and animator for this regular Squidward so we can animate
him.
So I'll just call this humanoid R standing for regular equal to regular Squidward dot humanoid.
And then we'll also get his animator.
So humanoid R dot animator.
And then we're also going to make some references to the idalene animation that is inside of our regular
Squidward.
So if you remember, when we set up our regular Squidward, we have our default idle animation and then
a bunch of other random idalene animations that we can play, and you should have updated those with
the different IDs that you uploaded from our anim saves.
But if you haven't done that yet, go ahead and save these animations to your Roblox account and then
take those IDs and put them into their respective animation instances.
But once we've done that, I'll make a reference to the idle animation for our regular Squidward, and
that's going to be in regular Squidward Dot idle Anim one.
And then we're also going to get all of the different idle animes that is inside of that folder.
So regular Squidward.
Not idle animes, and we can go ahead and get all of those different ones.
And then I'm going to go ahead and load that basic, uh, idle animation and get a track from it.
So we're going to call it Idle Anim Track.
And this is going to be again for regular Squidward.
So we're going to use the animator on him and load the animation of Idle Anim regular.
Okay, so this section is for regular Squidward.
And now let's create some variables and references to our handsome Squidward.
So handsome.
Squidward is in workspace.
Characters.
Dot.
Handsome.
Squidward.
We're going to get his humanoid, and we'll just prefix it with H to stand for handsome.
So handsome.
Squidward.
Dot humanoid and then get his animator as well.
And then we can go ahead and make a reference to his idle animation.
So idle anim handsome is equal to handsome.
Squidward dot idle anim one.
And then we'll load that animation on him as well.
So idle and Amtrak for handsome.
Handsome is equal to animator H.
And we're going to load this idol and handsome onto him.
And then last but not least, I'm going to create a new random data type.
Okay, now we're going to need a few private functions.
One function we'll need to change the lights in our game, or basically turn them on and turn them off.
So we can call this toggle lights.
And it'll get passed a boolean of whether or not we want to set them on or set them off.
So we can just call it set on.
And this will be a boolean.
We'll need a function to change the visibility of our different Squidward friends, or in this case,
we're going to be changing the, uh, visibility of our regular Squidward so we can call this function
set Reg Squidward visibility, and we can set this to a boolean of either true or false if we want them
to be visible or not visible.
And then we're going to need a function to get a random, uh, animation from our where is it from our,
uh, idle animations here.
So we can go ahead and call this function get random track standing for animation track.
So actually what we need to do here is we also need to load all of the different idle animations for
our regular Squidward.
So what we can do is we can loop through every single animation in idle animes.
And what we're going to do is we're going to load those animations and we can store them inside of a
table, and we can call it idle anim tracks.
So we put this table here.
And what we can do is we can insert into the table the different idle animation tracks.
So what we could do is we could get this animation and use our animator on our regular Squidward and
load this particular animation.
And this will return back to us an animation track, so we can call it track, and then we can insert
this track into our Idle Anim Tracks table.
All right.
And then with this function, this should be pretty easy.
All we can do is we can just return one of these random tracks so we can do idle anim tracks.
And we're going to use our RNG to get a random one.
So we'll use next integer from starting the index at one to the max number of idle anim tracks.
And it's just going to give us a random animation track.
So we can actually denote that here with animation track.
So that's what our good old function returns here.
So inside of our start function, what we need to do is we need to have, um two loops.
One loop is going to constantly play the animation on a regular Squidward, and it's going to wait for
when that idle animation ends.
And when it ends, it'll have a random chance to play one of the other different idle animation tracks
that we have stored inside of the table here.
And then we're going to need another loop that's going to constantly loop forever.
And if some random number is reached, then what we could do is we could flicker the lights and make
our Squidward disappear and have that ambience effect.
So that means we're going to have to spawn them in two separate threads, and we can use task Dot defer
to do this because we don't need it to run instantaneously.
So we could do task dot, defer and spawn a new function.
And this will have a while loop that will run forever and it'll pick out random different animation
tracks.
So what I'm going to do down here is I'm going to get our idle anim track on our handsome Squidward,
and we're going to play that.
And then what we're going to do up here is inside of our while loop.
We're going to check if the idle anim track.
Idle and Amtrak on our regular Squidward is plain.
So if it's plain or if it's not plain, I mean, then we need to play it so.
Idle and Amtrak regular play.
And then what we're going to do with this idle animation track is we're going to wait for it to complete.
Or basically we had that, uh, event inside of our idle animation, if you remember, it was called
ended.
So we need to wait for that marker to get reached so we can pass our idle anim track regular and use
the function get marker reach signal.
And the name was ended.
So when this marker is reached then we'll stop yielding.
And once we stop yielding, what we're going to do is we're going to use our RNG function and have the
chance of something like 1 to 8 is equal to one.
Then what we could do is we could get a random track.
So local track is equal to get random track.
And then we're going to play this track.
And then we're just going to wait for this track to end.
Because these are the tracks that do not loop.
But our idle animation track regular does loop.
Okay, so we'll have both the idle animation on our regular Squidward plane, and then we'll have the
idle animation on our handsome Squidward plane.
And what we need to do down here is create another loop using task Dot defer.
We'll spawn a new function.
So while true, do.
And what we're going to do is we're going to have a random chance if RNG next integer we could do something
like 1 to 15.
If this is equal to one then we can go ahead and flicker the lights and change the visibility for our
Squidward and stuff like that.
So what we could do here is we could access our play sound event.
And we could fire to all of the clients in the game to play a particular flickering sound.
You could also play this flickering sound on the server as well.
You don't have to use this event, but we're going to be using this particular module in the next section
of our game.
So it's kind of good to get used to how to use it now, but you can go ahead and do it anyway.
You can either just play the different flicker sounds directly from the server, or you can fire to
all the clients to tell them to play a particular sound on their end.
It doesn't really matter.
We're just doing this for practice sake so we can pick a random flickering sound.
So inside of flicker sounds, or actually we can go ahead and make a dedicated function for this as
well.
Why not.
So we can have this function be called get random flicker sound.
And what we'll do is we'll just return Flickr sounds.
We'll pass RNG next integer from one to the max number of Flickr sounds, and we'll get that back from
here, which will be a sound instance.
So this is a sound.
So we'll get our random flicker sound and we'll just send that to the different players.
So get random flicker sound.
And then once we tell them to play the flicker sound, that we can go ahead and change the lights or
toggle the lights in our game.
So toggle lights and we want them to be off.
So we could pass a boolean like false to this function.
And then we can actually go ahead and fill this out.
So we want our lights to be off.
So if set on is true then we'll turn on the lights.
Otherwise we'll turn off the lights.
And since in this case we want to turn off the lights, what we'll do is we'll loop through every single
light and ipairs workspace dot Krusty Krab, and there's a folder in there called lights that store
all the lights in our game.
And we can get every single descendant in there, because what we want to do is we want to check if
this descendant is a light instance.
So if light is a light instance.
Then what we need to do is we need to disable the slice.
So light dot enabled is equal to false.
Then the next thing we need to check is to see if this instance is a part that is neon.
So all of these different lights have this neon parts in them.
And we want to change the color of this neon part so it's not glowing anymore.
So what we could do is we could check if light is a base part.
And we want to check if the light material is equal to the enum dot material of neon.
And if it is, then what we could do is we could set an attribute on this light.
And we're going to call it original color, because we want to store what the original color of this
light was, and we'll just pass light color.
And then we're going to set light color to be basically black.
So we could actually create a constant for this.
We'll call it black and it will be equal to a new color three of 000.
So this is completely black.
And we'll just set the color of the light to this color.
Now if you want to turn on the lights then what we could do is we could basically just loop through
every single light again.
But this time if it is a light, then we want to enable the light.
And instead of setting the color to black, we want to set the light's color back to its original attributes.
So light dot color is going to be equal to light.
Get attribute original color.
So get attribute original color.
And that's all we need to do for this function.
So now when we call it here, the lights are going to be turned off.
And then once the lights get turned off, we want to make our regular Squidward disappear so we could
call our set regular Squidward visibility to false.
So we'll set it to false.
And that means we're going to have to fill out this function as well.
So inside of this function, what we could actually do is we could access our regular Squidward, get
his body, which is called Squidward Reg, and set the transparency of this equal to a number based
on this boolean.
And you might be thinking, oh yeah, we could do that with if statements, but actually we could also
use the and and the or keywords as a ternary operator.
Now what is a ternary operator?
Well, a ternary operator is a special kind of operator that exists in some programming languages that
allow you to get a value based on if a condition is true or false.
So, for example, if a condition was true, you could get a number like five, otherwise you could
get zero, something like that.
Now Lua doesn't have a dedicated ternary operator, but we can actually imitate a ternary operator using
the and and or keywords.
So if I go down to our command line down here and I print out a boolean in the console, like true,
you're going to be like, yep, it prints true.
Whatever.
Now if I print true and seven, what do you think is going to get printed out?
Do you think true is going to get printed out?
Well, if I hit enter, as you can see, seven gets printed out because when we're using the and keyword,
what is happening is that each value is being checked for whether or not they're falsy or truthy.
So since true is truthy and moved to the next condition, and since seven is truthy, it would move
to the next condition.
But since this is the last condition, this is the value that gets returned at the end of this little
section here, which is why seven got printed into the console.
So that means I can keep adding something else like five.
So if I print it out.
True.
And seven and five, since five is going to be our last value checked, and since all the other previous
values were truthy, five would get printed into the console.
Now, if I made this false here in the middle, what's going to happen instead is that it's not going
to print true or phi, but instead it's going to print false because that's the value that made this
condition here.
False.
So if I hit enter there we go.
We get false into the console.
Now, this is very powerful because we can create very concise statements that act like a ternary operator.
So let's say I had some kind of condition here, and based on this condition, I wanted to get either,
uh, a number one or a number zero.
So what I could do is I could have this condition and then use the and keyword and pass one or pass
zero.
So if condition is true, it'll pass one.
Otherwise if condition is false it'll skip one and pass zero instead thanks to the Or keyword.
So if I pass true here, we're going to get one printed into the console.
There we go.
But if I pass false here we're going to get zero printed into the console just like that.
So that means we can use this boolean to create a very concise statement.
So what I could do is I could set the transparency of our squid word equal to bool and 0 or 1.
So what this is going to do is if bool is true, if we want to set the visibility of our Squidward to
true, then it's going to set the transparency to be zero or opaque.
Otherwise, if bool is false, it's going to skip zero, and it's going to set it to be one instead
or fully transparent.
Pretty cool.
And we need to do the exact same thing for the hat of our Squidward as well.
So we could do regular Squidward dot hat dot transparency equal to bool and 0 or 1.
So now when we go back, once we have flickered the lights and then turned them off and then made our
regular Squidward disappear, then we're going to wait for a random amount of time so we could do task
dot wait and do RNG next number and wait anywhere from one to something like 1.7 seconds.
And then what we're going to do again is we're going to flicker the lights, but turn them back on.
So we'll get a random flicker sound and we'll set the lights to be on.
And then we'll wait again on the next number.
We could weight something like 0.6 to 1.5 seconds, and then this time we're going to turn the lights
back off again.
So false.
And then we're going to set our handsome Squidward to be somewhere randomly on the map so we could do
handsome Squidward humanoid route part dot C frame and set it equal to a random position so we get random
positions and pass RNG.
Next integer one to the max number of random positions, and we can get the key frame from that particular
part.
Now again, we could also put this into a function if you'd like.
So this main while loop down here looks very clean.
So what we could do is we could actually make one more private function.
We can call it get random position.
And what we'll do is we'll just return random positions RNG next integer one two number of random positions.
So this will return a bass part.
And from this base part we can go ahead and get the C frame.
So get random position, and then we get the C frame from that random position and set that on the humanoid
root part of our handsome Squidward.
So now our handsome Squidward will be somewhere randomly on the map, and then we can go ahead and wait
for another random amount of time, like somewhere.
Oh, I don't know, maybe between 1.5 and 2.1 seconds.
So that way it stays a little bit darker for longer.
And then again, we can just basically copy the same thing here, but turn the lights back on.
Well, wait another random amount of time, but I want to wait a little bit.
Uh, shorter amount of time.
So what's going on here is that the lights turn off, and then our regular Squidward disappears.
We wait a little bit, the lights turn back on, and then all the players see that our regular Squidward
disappear.
Lights turn back off again, and we put our handsome Squidward somewhere randomly on the map.
Lights turn back on and we want the lights to turn back on for only a small amount of time.
That way the players don't get to see our handsome Squidward for too long, so we could do Orangie next
number anywhere between 0.1 to, I would say, a max of like 0.35 seconds, and then we would go ahead
and turn the lights back off again.
And then we would want to set our handsome Squidward humanoid route part C frame, equal to that default
position dot C frame.
So is off of the map.
And again we're going to wait anywhere between R and G next number or next.
Next number.
0.5 to like 0.9 seconds.
And then after that, we can go ahead and turn the lights back on and make sure our regular squidward's
visibility is set to true, so we could set his visibility back to true.
And then we could go ahead and turn the lights back on.
And once we're done going through this if statement, then we can go ahead and wait for one second in
this while loop.
So that way this isn't constantly running all of the time.
So that means about an average of every 15 seconds the lights should flicker inside of our building.
So let's go ahead and test it out.
So if we go and test play our game here, so far everything has loaded well on both the client and the
server.
But actually we did get an error in our Squidward service.
So wrong.
Number of arguments to insert.
We accidentally filled out the insert function improperly, because we actually need to pass the item
that we want to insert into idle and tracks, which is our track.
All right, easy error we fixed.
Let's go ahead and test that out again.
No errors.
Everything loaded perfectly.
Wow.
It actually already wanted to flicker.
Let's actually go ahead and wait for another flicker to happen.
So we see our regular Squidward.
He's just chilling back there and hopefully the lights will flicker soon.
All right.
Lights flickered.
He's gone.
Oh, we see our handsome Squidward up there.
He disappears, and our regular Squidward comes back.
So very nice ambiance we have.
We're able to move our camera around.
The camera shakes a little bit.
We've got nice music playing in the background.
You can hear muffled rain playing and players are able to create servers here.
Thunder in the background and all that kind of fun stuff.
So our lobby is basically complete.
Actually, the next thing we need to do is we need to publish our game, make sure that, uh, teleporting
to the next place works, and go ahead and get started on the next section of our project.
So if you're ready to start in the next section, I'll go ahead and see you in the next lecture.